home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 201-225 / 214 / mandelvroom / src / getfile.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  19KB  |  667 lines

  1. /************************************************************************
  2. req.c
  3.         This file contains a general-purpose <requester> that
  4. will prompt the user for a filename input.
  5.         The program actually uses a window instead of a 'Requester'
  6. for greater flexibility. It will take control of your window's
  7. IDCMP Port when called.
  8.  
  9. ***     This material is copyright (c) 1986 by C. Heath of Microsmiths, Inc.
  10. Permission is granted to use these files in any way with the following
  11. exceptions:
  12.  
  13. 1) The files shall not be posted on any telecommunications service, public
  14. or private, except for BIX until January 15, 1987.
  15.  
  16. 2) The files may only be distributed in archive format, with no modifications.
  17. If you make any improvements on the file requester and would like to
  18. generally distribute them, please contact "cheath" on BIX, or write to:
  19.         Microsmiths Inc, PO Box 561, Cambridge, MA 02140
  20.  
  21. 3) The requester may be used in any commercial product, but must be in
  22. object code format.  You are free to make modifications for use in your
  23. product.  Permission is granted to Lattice, Inc, and to Manx, Inc, to
  24. include the source files in archive format.
  25.  
  26.         Thank you, and enjoy.
  27.                 ...cheath
  28.  
  29. ************************************************************************/
  30.  
  31. #include "standard.h"
  32. #include "safeclose.h"
  33.  
  34. #define FAST register
  35. #define NL NULL
  36.  
  37. extern char *dmore(), *dinit();
  38.  
  39. static struct FileLock      *pdir = NL;
  40. static struct FileInfoBlock *dir_info;
  41.  
  42. static struct Window   *eW;             /* Parent Window. Uck   */
  43.  
  44. static struct TextAttr MyFont = {"topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT };
  45.  
  46. /* FGAD requires a few unique gadget-ids, origined at FGAD      */
  47. /* In the unlikely event this conflicts with any of your gadgets, */
  48. /* change this equate to allow 16 contiguous unique ID's        */
  49.  
  50. #define FGAD    0x76c0L
  51.  
  52. #define FCHARS  32L     /* Number of chars allowed in file name */
  53.  
  54. #define DIR_SIZ 50L     /* Number of chars in a dir name...     */
  55. #define MAX_STR DIR_SIZ+2L
  56.  
  57. #define DENTS   5L              /* Number of entries on screen   */
  58. /* It's not as simple as changing 'DENTS'...      */
  59.  
  60. #define DSIZE   FCHARS+1L       /* Size of a directory entry   */
  61.  
  62. #define DBUFSIZ 3000L   /* Number of bytes to allocate for all ents */
  63.  
  64. #define BCOL    1L      /* Background color     */
  65. #define FCOL    2L      /* Foreground color     */
  66.  
  67. #define RHGHT   120L
  68. #define RWDTH   320L
  69.  
  70. #define ZWDTH   270L
  71.  
  72. static char     ubuf[MAX_STR];          /* Undo buffer  */
  73.  
  74. static struct dirent { struct dirent *next; BOOL isfile; char dE[DSIZE+2]; };
  75. static struct dirent *FirstEntry;
  76. static struct dirent *NextEntry;
  77.  
  78. static struct dirhead { struct dirent *next; };
  79. static struct dirhead ListHead;
  80.  
  81. static long   curent,maxent;
  82. static BOOL   more;
  83.  
  84. static struct Window    *wRq = NL;              /* Requester window   */
  85. static struct RastPort  *wRp;
  86.  
  87. /* Requester "Hailing" prompt */
  88. static struct IntuiText oTxt = {2,2,JAM1,10,11,NL, NL ,NL};
  89.  
  90. static struct IntuiText saydir = {0,1,JAM2,0,1,&MyFont,(UBYTE *)"(dir) ",NL};
  91.  
  92. static struct IntuiText rname[DENTS] = { /* File name list */
  93.    {2,1,JAM2,48,1,NL,NL, NL},
  94.    {2,1,JAM2,48,1,NL,NL, NL},
  95.    {2,1,JAM2,48,1,NL,NL, NL},
  96.    {2,1,JAM2,48,1,NL,NL, NL},
  97.    {2,1,JAM2,48,1,NL,NL, NL} };
  98.  
  99. /* Display for file name ... */
  100.  
  101. static SHORT oXY2[] = {-2,-2, RWDTH-78,-2, RWDTH-78,9, -2,9, -2,-2};
  102. static struct Border thebd = {0,0, 2,3,JAM1, 5,oXY2, NL};
  103.  
  104. static struct IntuiText otxt = {2,2,JAM1,-40,0,&MyFont,(UBYTE *)"file",NL};
  105. static struct StringInfo osx = { NL ,ubuf, NL,DSIZE,NL,NL,NL,NL,NL,NL,NL,NL,NL};
  106. static struct Gadget ogx = { NL, 60,RHGHT-35,RWDTH-80 ,10,     /* File name gadget */
  107.    GADGHCOMP, RELVERIFY , STRGADGET,
  108.    (APTR)&thebd,NL,&otxt,NL,(APTR)&osx, FGAD+11,NL };
  109.  
  110. static struct Gadget oga = { &ogx, 10,70, ZWDTH,10,   /* Gadgets For   */
  111.    GADGHCOMP, RELVERIFY, BOOLGADGET,     /* Directory entries   */
  112.    NL,NL, &rname[4] ,NL,NL, FGAD+10,NL };
  113. static struct Gadget og9 = {&oga, 10,60, ZWDTH,10,
  114.    GADGHCOMP, RELVERIFY, BOOLGADGET,
  115.    NL,NL, &rname[3] ,NL,NL, FGAD+9,NL };
  116. struct Gadget og8 = {&og9, 10,50, ZWDTH,10,
  117.    GADGHCOMP, RELVERIFY, BOOLGADGET,
  118.    NL,NL, &rname[2] ,NL,NL, FGAD+8,NL };
  119. static struct Gadget og7 = {&og8, 10,40, ZWDTH,10,
  120.    GADGHCOMP, RELVERIFY, BOOLGADGET,
  121.    NL,NL, &rname[1] ,NL,NL, FGAD+7,NL };
  122. static struct Gadget og6 = {&og7, 10,30, ZWDTH,10,
  123.    GADGHCOMP, RELVERIFY, BOOLGADGET,
  124.    NL,NL, &rname[0] ,NL,NL, FGAD+6,NL };
  125.  
  126.  
  127. /* Gadjets for requester  */
  128.  
  129. static SHORT oXY3[] = {0,0, 50,0, 50,9, 0,9, 0,0};
  130. static SHORT oXY4[] = {2,-2, 48,-2, 52,2, 52,7, 48,11, 2,11, -2,7, -2,2, 2,-2};
  131. static struct Border obd2 = {0,0, 2,3,JAM1, 9,oXY4, NL};
  132. static struct Border obd1 = {0,0, 3,2,JAM1, 5,oXY3, &obd2};  /* OTAY / CANCEL box */
  133.  
  134. static struct IntuiText ot1  = {0,0,JAM1,1,1,&MyFont,(UBYTE *)"  OK  ",NL};
  135. static struct IntuiText ot2  = {0,0,JAM1,1,1,&MyFont,(UBYTE *)"Cancel",NL};
  136. static struct IntuiText ot25 = {0,0,JAM1,1,1,&MyFont,(UBYTE *)"Device",NL};
  137.  
  138. static struct IntuiText dtxt = {2,2,JAM1,-60,0,NL,(UBYTE *)"drawer",NL};
  139. static struct StringInfo os5 = { NL ,ubuf, NL,DIR_SIZ,NL,NL,NL,NL,NL,NL,NL,NL,NL};
  140. static struct Gadget og5 = { &og6, RWDTH/2-80,19,190,10,     /* Directory */
  141.    GADGHCOMP, RELVERIFY, STRGADGET,
  142.    NL,NL,&dtxt,NL,(APTR)&os5, FGAD+5,NL };
  143.  
  144. static struct Image   cc_img;
  145. static struct PropInfo   cc_prop = {AUTOKNOB | FREEVERT, 0,0, 0,0x1000,0,0,0,0,0,0 };
  146. static struct Gadget og3 = { &og5,RWDTH-39,20,20,60,      /* Scroll Bar   */
  147.     GADGHCOMP,GADGIMMEDIATE | FOLLOWMOUSE, PROPGADGET,
  148.     (APTR)&cc_img,NL,NL,NL,(APTR)&cc_prop,FGAD+3,NL };
  149.  
  150. static struct Gadget og25 = { &og3, RWDTH-70,RHGHT-20, 50,10,  /* CANCEL */
  151.    GADGHCOMP,  RELVERIFY, BOOLGADGET,
  152.    (APTR)&obd1,NL, &ot2,NL,NL, FGAD+2,NL };
  153.  
  154. static struct Gadget og2 = { &og25, 136,RHGHT-20, 50,10,  /* DEVS */
  155.    GADGHCOMP,  RELVERIFY, BOOLGADGET,
  156.    (APTR)&obd1,NL, &ot25,NL,NL, FGAD+20,NL };
  157.  
  158. static struct Gadget og1 = { &og2, 20,RHGHT-20, 50,10,      /* OTAY   */
  159.    GADGHCOMP,           /* Flags        */
  160.    RELVERIFY,           /* Activation   */
  161.    BOOLGADGET,
  162.    (APTR)&obd1,NL,      /* GadgetRender, SelectRender   */
  163.    &ot1,NL,NL,          /* IntuiText, MutualExclude,SpecialInfo   */
  164.    FGAD+1,NL };         /* Gadget Id, UserData  */
  165.  
  166. /* Open a requester "Window" */
  167.  
  168. static struct NewWindow NewFiles = {
  169.    0, 0, RWDTH,RHGHT, BCOL,FCOL, NL, /* Fill in AFTER opening ... */
  170.    SMART_REFRESH | ACTIVATE | RMBTRAP | WINDOWDRAG,
  171.    &og1,NL,NL, NL,
  172.    NL, RWDTH,RHGHT,RWDTH,RHGHT, CUSTOMSCREEN };
  173.  
  174. IMPORT struct Library   *IntuitionBase;
  175.  
  176. /***************************************************
  177. *  get_fname(window,screen,hail,ddef,ddir);
  178. *
  179. *   Displays a window/requester that
  180. * gets a file name for device,directory,default file, extension
  181. *
  182. *   Calling args:
  183. * window:   Window making the request
  184. * screen:   Screen, if NULL assummed workbench
  185. * hail:   Text prompt at top of requester
  186. * ddef:   Input default file-name. Has NO DIRECTORY OR EXTENSION.
  187. * ddir:   Directory of file, may be null
  188.  
  189. /* Set a file-requester with prompt 'hail'   */
  190.  
  191. char *get_fname(cW,screen,hail,ddef,ddir)
  192.    struct Window *cW;           /* Calling Window   */
  193.    struct Screen *screen;       /* screen .... if null assumed workbench */
  194.    UBYTE        *hail;          /* Hailing prompt   */
  195.    char         *ddef;          /* Proable file-name   */
  196.    char         *ddir;          /* Directory in which to search   */
  197.    {
  198.    FAST struct IntuiMessage *imes;   /* Wait for message in HERE   */
  199.    FAST struct Gadget   *igad;   /* Get Gadjet Mumbo Jumbo   */
  200.    FAST long    i,class;
  201.    FAST TEXT    *pnam;
  202.  
  203.    FAST char    *retval;
  204.    FAST BOOL    dir_flag;
  205.    FAST BOOL    keepon;
  206.  
  207.    if ( ! (eW = cW) )   return(NL);
  208.  
  209.    osx.Buffer = ddef;   /* Set default file name   */
  210.    os5.Buffer = ddir;   /* Set default device name   */
  211.  
  212.    for ( i=0; i<DENTS; i++)
  213.       {
  214.       rname[i].IText = "";
  215.       rname[i].NextText = NL;
  216.       };
  217.  
  218.    NewFiles.Title = eW->Title;
  219.    if ((dir_info = AllocMem((long)sizeof(struct FileInfoBlock),0L)) == NULL)
  220.       return(NL);
  221.  
  222.    if (screen)          /* User supplied a screen */
  223.       {
  224.       NewFiles.Type = CUSTOMSCREEN;
  225.       NewFiles.Screen = screen;
  226.       }
  227.  
  228.    if ( ! (FirstEntry = (struct dirent *)AllocMem((long)DBUFSIZ,0L)) ||
  229.         ! (wRq = (struct Window *)OpenWindow( &NewFiles )) )
  230.       {
  231.       if (!FirstEntry)
  232.         notify("Can't Open first entry");
  233.       if (!wRq)
  234.         notify("Can't Open new window");
  235.       if ( FirstEntry )   FreeMem(FirstEntry,(long)DBUFSIZ);
  236.       /* notify("Can't Open Requester..."); */
  237.       FreeMem(dir_info,(long)sizeof(struct FileInfoBlock));
  238.       return(NL);
  239.       }
  240.    /* Set up directory, notify any errors...   */
  241.    if ( pnam = (char *)dinit(ddir) )   notify(pnam);
  242.  
  243.  
  244.    /* This optional line will activate a string gadget  */
  245.    if ( IntuitionBase->lib_Version > 32 )
  246.         {
  247.         ActivateGadget(&ogx,wRq,0L);
  248.         }
  249.  
  250.    wRp = wRq->RPort;
  251.  
  252.    wRq->UserPort = eW->UserPort;
  253.    ModifyIDCMP(wRq,(long)(MOUSEBUTTONS | GADGETDOWN | GADGETUP | MOUSEMOVE));
  254.  
  255.    SetAPen(wRp,1L);
  256.    RectFill(wRp,4L,10L,(long)(RWDTH-5),(long)(RHGHT-4));
  257.  
  258.    oTxt.IText = hail;   /* Set calling arg   */
  259.    oTxt.LeftEdge = (RWDTH - IntuiTextLength(&oTxt)) >> 1L;
  260.    PrintIText(wRp,&oTxt,0L,0L);
  261.  
  262.    RefreshGadgets(&og1,wRq,(long)NL);
  263.    for ( retval= NL, keepon=TRUE; keepon ; )
  264.       {
  265.       while ( ! (imes=(struct IntuiMessage *)GetMsg(wRq->UserPort)) )
  266.       {
  267.          if ( dir_flag )
  268.             {
  269.             i = (maxent-DENTS) * cc_prop.VertPot / MAXBODY;
  270.             if ( i > (maxent-DENTS) )
  271.             i = maxent-DENTS;
  272.             if ( i <0 )   i = 0;
  273.             curent = i;
  274.             cxxx();
  275.             dir_flag = FALSE;
  276.             }
  277.          if ( more )
  278.             {
  279.             if (pnam = (char *)dmore())   /* Continue to read the directory */
  280.                notify(pnam);      /* Yucko error   */
  281.             if ( maxent <= DENTS ) dir_flag = TRUE;
  282.             }
  283.          else    WaitPort(wRq->UserPort);
  284.          }
  285.       igad = (struct Gadget *)imes->IAddress;
  286.       class = imes->Class;
  287.       ReplyMsg(imes);
  288.  
  289.       switch (class)
  290.          {
  291.          case MOUSEMOVE:      dir_flag = TRUE;   break;
  292.  
  293.          case GADGETUP:
  294.          case GADGETDOWN:
  295.             switch ( i = igad->GadgetID)
  296.             {
  297.  
  298.             case FGAD+20:       /* Get device list                  */
  299.                RemoveGadget(wRq,&og5);  /* File name gadget */
  300.                ddir[0] = '\0';
  301.                AddGadget(wRq,&og5,-1L);
  302.                RefreshGadgets(&og5,wRq,(long)NL);
  303.                getdisks();
  304.                break;
  305.  
  306.             case FGAD+6:
  307.             case FGAD+7:
  308.             case FGAD+8:
  309.             case FGAD+9:
  310.             case FGAD+10:       /* Replace file or directory name   */
  311.                pnam = rname[i - (FGAD+6)].IText;
  312.                if ( rname[igad->GadgetID - (FGAD+6)].NextText == NL )
  313.                   {
  314.                   RemoveGadget(wRq,&ogx);  /* File name gadget */
  315.                   for (i=0; i<DSIZE; i++)      ddef[i] = *pnam++;
  316.                   AddGadget(wRq,&ogx,-1L);
  317.                   RefreshGadgets(&ogx,wRq,(long)NL);
  318.                   break;
  319.                   }
  320.                   else
  321.                   {
  322.                   RemoveGadget(wRq,&og5);  /* Scroll bar */
  323.                   rfnam(ddir,pnam);
  324.                   AddGadget(wRq,&og5,-1L);
  325.                   RefreshGadgets(&og5,wRq,(long)NL);
  326.                   }
  327.             case FGAD+5:
  328.                if ( pnam = (char *)dinit(ddir) )
  329.                   notify(pnam);
  330.             case FGAD+3:
  331.                dir_flag = TRUE;
  332.                break;
  333.  
  334.             case FGAD+11:      /* Name gadget, OTAY gadget   */
  335.             case FGAD+1:
  336.                retval = ddef;
  337.             case FGAD+2:      /* Cancel gadget   */
  338.                keepon = FALSE;
  339.             }
  340.          }
  341.       }
  342.  
  343.       FreeMem(FirstEntry,(long)DBUFSIZ );
  344.       FreeMem(dir_info,(long)sizeof(struct FileInfoBlock));
  345.       free_pdir();
  346.  
  347.       CloseWindowSafely(wRq);
  348.       return(retval);
  349.    }
  350.  
  351. static free_pdir()
  352.    {
  353.    if ( pdir )
  354.       {
  355.       UnLock(pdir);
  356.       pdir = NL;
  357.       }
  358.    }
  359.  
  360. /*****************************************************************
  361. * dvinit()
  362. *   Initialize the fib for directory muck.  Null return
  363. * is good, else return is a pointer to an error string      */
  364.  
  365. static char *dvinit(subdir)
  366.    char *subdir;
  367.    {
  368.    more = FALSE;
  369.    curent = maxent = 0;
  370.  
  371.    NextEntry = FirstEntry;      /* Allocate from here   */
  372.    ListHead.next = NL;          /* Clear the boogie     */
  373.  
  374.    free_pdir();   /* Unlock any old lock... */
  375.  
  376.    more = TRUE;
  377.    }
  378.  
  379.  
  380. static char *dvmore(device)
  381.   char *device;
  382.    {
  383.    FAST struct dirent   *p_D = NextEntry;
  384.    FAST struct dirent   *ptr = (struct dirent *)&ListHead;
  385.    FAST struct dirent   *plink;
  386.  
  387.    FAST   TEXT   *p_mung;
  388.  
  389.    FAST long    i;
  390.  
  391.    if ( ! more )   return(NL);
  392.  
  393.       if ( (ULONG)p_D >=
  394.          ((ULONG)FirstEntry + (ULONG)DBUFSIZ - (ULONG)sizeof(struct dirent)) )
  395.          {
  396.          more = FALSE;
  397.          return("Directory Truncated!");
  398.          }
  399.  
  400.  
  401.       /* Here you can add a file/directory filter   */
  402.       /* filename text string is at &p_D->dE[0   */
  403.       p_D->isfile = 0;
  404.       p_mung = &p_D->dE[0];
  405.  
  406.       for ( i=0; i<FCHARS; i++)
  407.          if ( ! (*p_mung++ = *device++) )   break;
  408.  
  409.       i = (long)p_mung;
  410.       NextEntry = (struct dirent *)( (i+5L) & ~3L );
  411.  
  412.       for ( i=maxent++; i>=0; i--)
  413.          {
  414.          if ( ! (plink = ptr->next)  )   break;
  415.          if ( alpha_lower(p_D,plink) )   break;
  416.          ptr = plink;
  417.          }
  418.  
  419.       p_D->next = plink;
  420.       ptr->next = p_D;
  421.  
  422.       return(NL);
  423. }
  424.  
  425. #include <exec/types.h>
  426. #include <exec/memory.h>
  427. #include <libraries/dos.h>
  428. #include <libraries/dosextens.h>
  429. #include <libraries/filehandler.h>
  430.  
  431. #include <stdio.h>
  432.  
  433. /* btoc() takes a pointer to a string in BCPL format and converts it to a
  434.  * C string.
  435.  */
  436. void *btoc(bstring)
  437. char *bstring;
  438. {
  439.  register UBYTE len,count,*cstring;
  440.  
  441.  cstring = (UBYTE *) bstring;
  442.  len = cstring[0];
  443.  for(count=0;count < len;count++)
  444.   cstring[count] = cstring[count+1];
  445.  cstring[count] = '\0';
  446. }
  447.  
  448. /* getdisks() will grab all disk device names in the system device list and
  449.  *  append an exec node to a given list. The node being named in respect to the
  450.  *  device.
  451.  */
  452. getdisks()
  453. {
  454.  extern struct DosLibrary         *DOSBase;
  455.  struct RootNode                  *rnode;
  456.  struct DosInfo                   *dinfo;
  457.  register struct DeviceNode       *dnode;
  458.  register struct Node             *adisk;
  459.  char     *bname,name[32];
  460.  
  461.  rnode   = (struct RootNode *)  DOSBase->dl_Root;
  462.  dinfo   = (struct DosInfo  *)  BADDR(rnode->rn_Info);
  463.  
  464.  dvinit();
  465.  
  466.  Forbid();
  467.  for(dnode = (struct DeviceNode *) BADDR(dinfo->di_DevInfo);BADDR(dnode);
  468.         dnode = (struct DeviceNode *) BADDR(dnode->dn_Next))
  469.   {
  470.    if(!dnode->dn_Type && dnode->dn_Task && BADDR(dnode->dn_Name))
  471.  
  472. /* if(dnode->dn_Task && BADDR(dnode->dn_Name))                      */
  473.     {
  474.      bname = (char *) BADDR(dnode->dn_Name);
  475.      movmem(bname,name,(ULONG)bname[0]+1L);
  476.      btoc(name); strcat(name,":");
  477.      dvmore(name);
  478.     }
  479.   }
  480.  Permit();
  481.  
  482.  more = FALSE;
  483.  cxxx();
  484. }
  485.  
  486. static char *dinit(subdir)
  487.    char *subdir;
  488.    {
  489.    more = FALSE;
  490.    curent = maxent = 0;
  491.  
  492.    NextEntry = FirstEntry;      /* Allocate from here   */
  493.    ListHead.next = NL;          /* Clear the boogie     */
  494.  
  495.    free_pdir();   /* Unlock any old lock... */
  496.  
  497.    if (! (pdir=(struct FileLock *)Lock(subdir,(ULONG)ACCESS_READ)) )
  498.       return("Wrong Diskette?");
  499.    if ( ! Examine(pdir, dir_info) )   return("Wierd Disk Error");
  500.    if ( dir_info->fib_DirEntryType < 0L )   return("Bizzare Alert!!");
  501.  
  502.    more = TRUE;
  503.    return(dmore());
  504.    }
  505.  
  506.  
  507. static char *dmore()
  508.    {
  509.    FAST struct dirent   *p_D = NextEntry;
  510.    FAST struct dirent   *ptr = (struct dirent *)&ListHead;
  511.    FAST struct dirent   *plink;
  512.  
  513.    FAST   TEXT   *p_mung;
  514.  
  515.    FAST long    i;
  516.  
  517.    if ( ! more )   return(NL);
  518.  
  519.    if ( ExNext( pdir, dir_info ) )
  520.       {
  521.  
  522.  
  523.       if ( (ULONG)p_D >=
  524.          ((ULONG)FirstEntry + (ULONG)DBUFSIZ - (ULONG)sizeof(struct dirent)) )
  525.          {
  526.          more = FALSE;
  527.          return("Directory Truncated!");
  528.          }
  529.  
  530.  
  531.       /* Here you can add a file/directory filter   */
  532.       /* filename text string is at &p_D->dE[0   */
  533.       p_D->isfile = ( dir_info->fib_DirEntryType < 0L );
  534.       p_mung = &p_D->dE[0];
  535.  
  536.       if ( IsInfo( dir_info->fib_FileName ) ) return(NL);
  537.  
  538.       for ( i=0; i<FCHARS; i++)
  539.          if ( ! (*p_mung++ = dir_info->fib_FileName[i]) )   break;
  540.  
  541.       i = (long)p_mung;
  542.       NextEntry = (struct dirent *)( (i+5L) & ~3L );
  543.  
  544.       for ( i=maxent++; i>=0; i--)
  545.          {
  546.          if ( ! (plink = ptr->next)  )   break;
  547.          if ( alpha_lower(p_D,plink) )   break;
  548.          ptr = plink;
  549.          }
  550.       p_D->next = plink;
  551.       ptr->next = p_D;
  552.  
  553.       return(NL);
  554.       }
  555.    else return ( IoErr() == ERROR_NO_MORE_ENTRIES) ?
  556.        (char *)(more = (long)NL) : "Error Reading Directory!!!";
  557.    }
  558.  
  559. IsInfo( str )
  560.   char *str;
  561. {
  562.   int len;
  563.  
  564.   len = strlen(str);
  565.  
  566.   if (len > 5) {
  567.     return( strcmp( str + len - 5, ".info" ) == 0 );
  568.   }
  569.  
  570.   return( 0 );
  571. }
  572.  
  573. /* dedicated alphabetizing function for dmore()   */
  574.  
  575. static alpha_lower(snew,sold)
  576.    struct dirent *snew,*sold;
  577.    {
  578.    FAST struct dirent *pnew = snew;
  579.    FAST TEXT *ps1,*ps2, c,d;
  580.  
  581.    if ( pnew->isfile == sold->isfile)
  582.       {
  583.       ps1 = &pnew->dE[0];
  584.       ps2 = &sold->dE[0];
  585.       while ( (c=*ps1++) )
  586.          {
  587.          if ( c > (d=*ps2++) )   return(FALSE);
  588.          else if ( c < d )      break;
  589.          }
  590.       return(TRUE);
  591.       }
  592.    return(pnew->isfile);
  593.    }
  594.  
  595.  
  596.  
  597. /* Display directory stuff   */
  598.  
  599. static cxxx()
  600.    {
  601.    FAST long   i,new;
  602.    FAST long   x,y;
  603.    FAST struct dirent *ohboy = (struct dirent *)&ListHead;
  604.  
  605.    new = curent;
  606.    for ( i=0; i<new; i++)   ohboy = ohboy->next;
  607.  
  608.    y = 20L;
  609.    for (i=0; i<DENTS; i++)
  610.       {
  611.       y += (x=10);
  612.       rname[i].NextText = NL;
  613.       rname[i].IText = "";
  614.       rname[i].LeftEdge = 0;
  615.       if ( (new+i) < maxent )
  616.          {
  617.          ohboy = ohboy->next;
  618.          rname[i].IText = &ohboy->dE[0];
  619.          if ( ohboy->isfile )   PrintIText(wRp,&rname[i],10L,y);
  620.          else
  621.             {
  622.             rname[i].LeftEdge = 48;
  623.             PrintIText(wRp,&saydir,10L,y);
  624.             PrintIText(wRp,&rname[i],10L,y);
  625.             rname[i].NextText = &saydir;
  626.             }
  627.          x = wRp->cp_x;
  628.          }
  629.       if ( x < ZWDTH+10 )   RectFill(wRp,x,y,(long)(ZWDTH+10),(long)(y+8L));
  630.       }
  631.    }
  632.  
  633.  
  634. /**************************************************
  635. * rfnam()
  636. *   Combines dir, plus name into dir   */
  637.  
  638. static rfnam(dir,fil_nam)
  639.    char *dir,*fil_nam;
  640.    {
  641.    FAST char   *pdst = dir;
  642.    FAST char   *psrc = fil_nam;
  643.    FAST char   c = ':';
  644.  
  645.    while ( *pdst )
  646.       c = *pdst++;
  647.    if ( c != ':')   *pdst++ = '/';
  648.  
  649.    while ( *pdst++ = *psrc++ )
  650.       ;
  651.    }
  652.  
  653. static struct IntuiText b_txt = {0,1,JAM2, 5,20,NL,NL,    NL};
  654. static struct IntuiText p_txt = {0,1,JAM2, 5,3,NL,"OK", NL};
  655.  
  656. /****************************************************************/
  657. /* notify(txt)                     */
  658. /*   Prompts for Yes/No response            */
  659.  
  660. static notify(txt)
  661.    char *txt;
  662.    {
  663.    b_txt.IText = txt;
  664.    AutoRequest(wRq,&b_txt,0L,&p_txt,0L,0L,
  665.       (long)(IntuiTextLength(&b_txt)+50L),70L);
  666.    }
  667.